/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_RTMP_AMF_H
#define MK_RTMP_AMF_H
#include "MkUtil/MkTime.h"


#define MkAmf3IntegerMax	268435455
#define MkAmf3IntegerMin	-268435456

typedef enum _amf_type
{
    MkAmfNumber = 0,
    MkAmfBoolean,
    MkAmfString,
    MkAmfTypeObject,
    MkAmfMovieClip, /* reserved, not used */
    MkAmfNull,
    MkAmfUndefined,
    MkAmfReference,
    MkAmfEcmaArray,
    MkAmfObjectEnd,
    MkAmfStrictArray,
    MkAmfDate,
    MkAmfLongString,
    MkAmfUnsuppoted,
    MkAmfRecordset,/* reserved, not used */
    MkAmfXmlDoc,
    MkAmfTypedObject,
    MkAmfAvmplus,//to amf3
    MkAmfInvalid = 0xff
}MkAmfType;

typedef enum _amf3_type
{
    MkAmf3Undefined = 0,
    MkAmf3Null,
    MkAmf3False,
    MkAmf3True,
    MkAmf3Integer,
    MkAmf3Double,
    MkAmf3String,
    MkAmf3XmlDoc,
    MkAmf3Date,
    MkAmf3Array,
    MkAmf3Object,
    MkAmf3Xml,
    MkAmf3ByteArray
}MkAmf3Type;

typedef struct _amf_object
{
    MkString                    Name;
    MkAmfType                   DataType;

    double                      NumberValue;
    MkString                    strValue;
    Uint32                      UintValue; //include bool value
    BOOL                        bValue;
    CMkTime                     TimeValue;
    MkVector<_amf_object>  VecObjectValue;
    _amf_object(const MkAmfType& dType = MkAmfInvalid)
    {
        DataType = dType;
    }
    _amf_object(const MkString& StrName, const MkAmfType& dType, double Number)
    {
        Name = StrName;
        DataType = dType;
        NumberValue = Number;
    }
    _amf_object(const MkString& StrName, const MkAmfType& dType, const MkString& Str)
    {
        Name = StrName;
        DataType = dType;
        strValue = Str;
    }
    _amf_object(const MkString& StrName, const MkAmfType& dType, Uint32 iValue)
    {
        Name = StrName;
        DataType = dType;
        UintValue = iValue;
    }
    _amf_object(const MkString& StrName, const MkAmfType& dType, const CMkTime& tValue)
    {
        Name = StrName;
        DataType = dType;
        TimeValue = tValue;
    }
    _amf_object(const MkString& StrName, const MkAmfType& dType, BOOL boolValue)
    {
        Name = StrName;
        DataType = dType;
        bValue = boolValue;
    }
}MkAmfObject;

class MkApi CMkAmf
{
public:
    //return decode end point if failed return nullptr  pEnd is buffer endpoint
    static const Uint8* DecodeUint8(const Uint8* pBegin, const Uint8* pEnd, Uint8& Value);
    static const Uint8* DecodeUint16(const Uint8* pBegin, const Uint8* pEnd, Uint16& Value);
    static const Uint8* DecodeUint24(const Uint8* pBegin, const Uint8* pEnd, Uint32& Value);
    static const Uint8* DecodeUint32(const Uint8* pBegin, const Uint8* pEnd, Uint32& Value);
    static const Uint8* DecodeNumber(const Uint8* pBegin, const Uint8* pEnd, double& dValue);
    static const Uint8* DecodeString(const Uint8* pBegin, const Uint8* pEnd, MkString& Value);
    static const Uint8* DecodeLongString(const Uint8* pBegin, const Uint8* pEnd, MkString& Value);
    static const Uint8* DecodeBoolean(const Uint8* pBegin, const Uint8* pEnd, BOOL& bValue);
    static const Uint8* DecodeDate(const Uint8* pBegin, const Uint8* pEnd, CMkTime& DTime);

    static const Uint8* DecodeAmf3Integer(const Uint8* pBegin, const Uint8* pEnd, Uint32& Value);
    static const Uint8* DecodeAmf3String(const Uint8* pBegin, const Uint8* pEnd, MkString& Value);

    static Uint8* EncodeUint8(Uint8* pBegin, Uint8* pEnd, Uint8 Value);
    static Uint8* EncodeUint16(Uint8* pBegin, Uint8* pEnd, Uint16 Value);
    static Uint8* EncodeUint24(Uint8* pBegin, Uint8* pEnd, Uint32 Value);
    static Uint8* EncodeUint32(Uint8* pBegin, Uint8* pEnd, Uint32 Value);
    static Uint8* EncodeString(Uint8* pBegin, Uint8* pEnd, const MkString& Value);
    static Uint8* EncodeLongString(Uint8* pBegin, Uint8* pEnd, const MkString& Value);
    static Uint8* EncodeNumber(Uint8* pBegin, Uint8* pEnd, double Value);
    static Uint8* EncodeBeginObject(Uint8* pBegin, Uint8* pEnd);
    static Uint8* EncodeBool(Uint8* pBegin, Uint8* pEnd, BOOL bValue);
    static Uint8* EncodeNamedString(Uint8* pBegin, Uint8* pEnd, const MkString& Key, const MkString& Value);
    static Uint8* EncodeEndObject(Uint8* pBegin, Uint8* pEnd);
    static Uint8* EncodeNamedNumber(Uint8* pBegin, Uint8* pEnd, const MkString& Key, double Value);
    static Uint8* EncodeNamedBool(Uint8* pBegin, Uint8* pEnd, const MkString& Key, BOOL bValue);
    static Uint8* EncodeDate(Uint8* pBegin, Uint8* pEnd, const CMkTime& DTime);

    static Uint8* EncodeObject(Uint8* pBegin, Uint8* pEnd, const MkVector<MkAmfObject>& VecObj);
    static Uint8* EncodeEcmaArray(Uint8* pBegin, Uint8* pEnd, const MkVector<MkAmfObject>& VecObj);
    static Uint8* EncodeArray(Uint8* pBegin, Uint8* pEnd, const MkVector<MkAmfObject>& VecObj);

    static const Uint8* DecodeObject(const Uint8* pBegin, const Uint8* pEnd, MkVector<MkAmfObject>& VecObj, BOOL bDecodeName);
    static const Uint8* DecodeEcmaArray(const Uint8* pBegin, const Uint8* pEnd, MkVector<MkAmfObject>& VecObj, BOOL bDecodeName);
    static const Uint8* DecodeArray(const Uint8* pBegin, const Uint8* pEnd, MkVector<MkAmfObject>& VecObj, BOOL bDecodeName);

    static const Uint8* DecodeAmf3Object(const Uint8* pBegin, const Uint8* pEnd, MkVector<MkAmfObject>& VecObj, BOOL bDecodeName);
    static Uint8* EncodeOneObject(Uint8* pBegin, Uint8* pEnd, const MkAmfObject& Obj);
protected:
private:
    static Uint8* EncodeName(Uint8* pBegin, Uint8* pEnd, const MkString& Name);


    static const Uint8* DecodeOneObject(const Uint8* pBegin, const Uint8* pEnd, BOOL bDecodeName, MkAmfObject& Obj);
    static const Uint8* Amf3DecodeOneObject(const Uint8* pBegin, const Uint8* pEnd, BOOL bDecodeName, MkAmfObject& Obj);
};

#endif